package com.tanhua.server.service;

import com.alibaba.fastjson.JSON;
import com.tanhua.autoconfig.templates.AipFaceTemplate;
import com.tanhua.autoconfig.templates.HuanXinTemplate;
import com.tanhua.autoconfig.templates.OssTemplate;
import com.tanhua.autoconfig.templates.SmsTemplate;
import com.tanhua.commons.utils.JwtUtils;
import com.tanhua.domain.db.SoulUserLock;
import com.tanhua.domain.db.User;
import com.tanhua.domain.db.UserInfo;
import com.tanhua.domain.mongo.UserLike;
import com.tanhua.domain.vo.LoveVo;
import com.tanhua.domain.vo.PageResult;
import com.tanhua.domain.vo.UserInfoVo;
import com.tanhua.domain.vo.UserLikeVo;
import com.tanhua.dubbo.api.db.SoulUserLockApi;
import com.tanhua.dubbo.api.db.UserApi;
import com.tanhua.dubbo.api.db.UserInfoApi;
import com.tanhua.dubbo.api.mongo.FriendApi;
import com.tanhua.dubbo.api.mongo.UserLikeApi;
import com.tanhua.server.exceptions.TanhuaException;
import com.tanhua.server.interceptors.UserHolder;
import io.jsonwebtoken.Claims;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.joda.time.DateTime;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.util.*;
import java.util.concurrent.TimeUnit;

@Service
public class UserService {

    @DubboReference
    private UserApi userApi;
    @DubboReference
    private UserInfoApi userInfoApi;
    @DubboReference
    private SoulUserLockApi soulUserLockApi;

    @Autowired
    private SmsTemplate smsTemplate;

    @Autowired
    private AipFaceTemplate aipFaceTemplate;

    @Autowired
    private OssTemplate ossTemplate;
    @Autowired
//    private RedisTemplate<String,String> redisTemplate;
    private StringRedisTemplate redisTemplate;

    @Autowired
    private HuanXinTemplate huanXinTemplate;

    @Autowired
    private RabbitTemplate rabbitTemplate;
    @DubboReference
    private UserLikeApi userLikeApi;
    @DubboReference
    private FriendApi friendApi;


    public ResponseEntity save(String phone, String password) {

        User user = new User();
        user.setMobile(phone);
        user.setPassword(DigestUtils.md5Hex(password) ); //加密
//        user.setCreated(new Date());
//        user.setUpdated(new Date());

        Long userId = userApi.save(user);
        return  ResponseEntity.ok(userId) ;
    }

    public ResponseEntity findByMobile(String mobile) {
        User user = userApi.findByMobile(mobile);
        return  ResponseEntity.status(HttpStatus.CREATED).body(user);
    }

//    发送短信
    public ResponseEntity sendSmsCode(String phone) throws Exception {
//        String randomNumeric = RandomStringUtils.randomNumeric(6);  //TODO 项目上线时要修改
        String randomNumeric = "123456";
//        smsTemplate.sendSms(phone,randomNumeric);  //TODO 项目上线时要修改
        System.out.println("验证码是："+randomNumeric);
//        存储验证码 redis中  设置5分钟的失效时间
        redisTemplate.boundValueOps("send_code_"+phone).set(randomNumeric,5, TimeUnit.MINUTES);
        return ResponseEntity.ok(null);
    }

//    返回结果： {"token":"rgsdgsd.adfgdd.adgasd","isNew":false}
    public ResponseEntity loginVerification(String phone, String verificationCode) {

//        1、从redis中获取验证码
//                如果获取不到 意味着验证码失效了
        String randomNumeric = redisTemplate.boundValueOps("send_code_" + phone).get();

        if(StringUtils.isBlank(randomNumeric)){
            throw new TanhuaException(666,"验证码失效");
        }
//        2、两个验证码比较
//                如果不相等，验证码错误
        if(!StringUtils.equals(verificationCode,randomNumeric)){
            throw new TanhuaException(666,"验证码错误");
        }
//        3、根据电话号码查询用户
        User user = userApi.findByMobile(phone);

        boolean isNew = false;

        if(user==null){
//            如果查不到，直接新增一个用户 根据用户信息生成token，并且返回
            user = new User();
            user.setMobile(phone);
            user.setPassword(DigestUtils.md5Hex("123456") ); //预留字段 ，这里先随便给一个密码
//            user.setCreated(new Date());
//            user.setUpdated(new Date());
            Long userId = userApi.save(user);
//            有个坑，大家注意
            user.setId(userId);

//            把新用户注册到环信上
            huanXinTemplate.register(userId);


            isNew = true;


            //        //将用户保存在lock表中  ----方案一

            SoulUserLock soulUserLock1 = new SoulUserLock();
            soulUserLock1.setUserId(user.getId().toString());
            soulUserLock1.setQuestionnaireId("1");
            soulUserLock1.setIsLock(0);
            soulUserLock1.setCreated(new Date());
            soulUserLock1.setUpdated(new Date());
            soulUserLockApi.save(soulUserLock1);
            SoulUserLock soulUserLock2 = new SoulUserLock();
            soulUserLock2.setUserId(user.getId().toString());
            soulUserLock2.setQuestionnaireId("2");
            soulUserLock2.setIsLock(1);
            soulUserLock2.setCreated(new Date());
            soulUserLock2.setUpdated(new Date());
            soulUserLockApi.save(soulUserLock2);
            SoulUserLock soulUserLock3 = new SoulUserLock();
            soulUserLock3.setUserId(user.getId().toString());
            soulUserLock3.setQuestionnaireId("3");
            soulUserLock3.setIsLock(1);
            soulUserLock3.setCreated(new Date());
            soulUserLock3.setUpdated(new Date());
            soulUserLockApi.save(soulUserLock3);









        }
//                如果查到了，根据用户信息生成token，并且返回
        Map claims = new HashMap();
        claims.put("id",user.getId());
        claims.put("mobile",user.getMobile());
        String token = JwtUtils.createToken(claims);

//        {"token":"rgsdgsd.adfgdd.adgasd","isNew":false}

        Map resultMap = new HashMap();
        resultMap.put("token",token);
        resultMap.put("isNew",isNew);

//        插入tb_log数据
//        logApi.save(log); 向mq中放的消息有：操作人、操作类型、操作时间

//        `type` varchar(255) NOT NULL COMMENT '操作类型,0101为登录，0102为注册，0201为发动态，0202为浏览动态，0203为动态点赞，0204为动态喜欢，0205为评论，0206为动态取消点赞，0207为动态取消喜欢，0301为发小视频，0302为小视频点赞，0303为小视频取消点赞，0304为小视频评论',

        Map mqMap = new HashMap();
        mqMap.put("userId",user.getId());
        mqMap.put("type",isNew?"0102":"0101");
        mqMap.put("logTime", DateTime.now().toString("yyyy-MM-dd"));
        String jsonString = JSON.toJSONString(mqMap);
        rabbitTemplate.convertAndSend("log.exchange","user.log",jsonString);

        return ResponseEntity.ok(resultMap);

    }

    public ResponseEntity loginReginfo(String token, UserInfo userInfo) {
        User user = getUserFromToken(token);
        userInfo.setId(user.getId());
//        userInfo.setCreated(new Date());
//        userInfo.setUpdated(new Date());
        // TODO 作业：计算年龄   userInfo.setAge();
        userInfoApi.save(userInfo);

        return ResponseEntity.ok(null);


    }

    public User getUserFromToken(String token) {
        Claims claims = JwtUtils.getClaims(token);
        Long id = claims.get("id", Long.class);
        String mobile = claims.get("mobile", String.class);
        User user = new User();
        user.setId(id);
        user.setMobile(mobile);
        return user;
    }


    public ResponseEntity loginReginfoHead(String token, MultipartFile headPhoto) throws Exception {
//        1、判断是否为人脸
        boolean isFace = aipFaceTemplate.detect(headPhoto.getBytes());
        if(!isFace){
            throw new TanhuaException(500,"请重新上传人脸照片");
        }
//        2、上传到阿里云 获取到url
        String avatarUrl = ossTemplate.upload(headPhoto.getOriginalFilename(), headPhoto.getInputStream());
//        3、修改用户的avatar   update tb_user_info set avatar =?? where id=?

        UserInfo userInfo = new UserInfo();
        User user = getUserFromToken(token);
        userInfo.setId(user.getId());
        userInfo.setAvatar(avatarUrl);
        userInfoApi.update(userInfo);


        return ResponseEntity.ok(null);

    }

    public ResponseEntity findUserInfoById(Long id) {
//        查询的是UserInfo，返回的是UserInfoVo
        UserInfo userInfo = userInfoApi.findById(id);

        UserInfoVo userInfoVo = new UserInfoVo();
        BeanUtils.copyProperties(userInfo,userInfoVo); // 属性名和数据类型要一致才行
        if(userInfo.getAge()!=null){
            userInfoVo.setAge(userInfo.getAge().toString()); //这里有坑
        }
        return ResponseEntity.ok(userInfoVo);

    }

    public ResponseEntity updateUserInfo(UserInfo userInfo) {
//        update tb_user_info set XX=?? ,XX=?? ,XX=?? where id=?
        Long id = UserHolder.getUserId();
        userInfo.setId(id);
        userInfoApi.update(userInfo);
        return ResponseEntity.ok(null);
    }

    //统计
    public ResponseEntity eachLove() {
        Long userId = UserHolder.getUserId();
        List<UserLike> userLikeList = userLikeApi.find(userId);
        LoveVo loveVo = new LoveVo();
        Integer eachLoveCount = 0;
        Integer loveCount = 0;
        //遍历我喜欢的人的列表
        for (UserLike userLike : userLikeList){
            Long likeUserId = userLike.getLikeUserId();
            //如果也喜欢我，就是相互喜欢
            //不喜欢我，就是喜欢
            Boolean isExist1 = userLikeApi.isExist(likeUserId,userId);
            if (isExist1){
                eachLoveCount++;
            }else{
                loveCount++;
            }
        }
        Integer loveMeCount = userLikeApi.getCount(userId);   //喜欢我的
        //粉丝=喜欢我的-互相喜欢的
        Integer fanCount = loveMeCount - eachLoveCount;
        loveVo.setEachLoveCount(eachLoveCount);
        loveVo.setLoveCount(loveCount);
        loveVo.setFanCount(fanCount);
        return ResponseEntity.ok(loveVo);
    }
    //展示互相喜欢列表
    public ResponseEntity eachLovePage(Integer page, Integer pagesize, String nickname) {
        Long userId = UserHolder.getUserId();
        //页面-我喜欢的人
        PageResult pageResult = userLikeApi.lovePage(userId,page,pagesize);
        List<UserLike> userLikeList = (List<UserLike>) pageResult.getItems();
        List<UserLikeVo> userLikeVoList = new ArrayList<>();
        for (UserLike userLike : userLikeList){
            UserInfo userInfo = userInfoApi.findById(userLike.getLikeUserId());
            UserLikeVo userLikeVo = new UserLikeVo();
            //如果也喜欢我，就是相互喜欢
            if (userLikeApi.isExist(userLike.getLikeUserId(),userId)){
                BeanUtils.copyProperties(userInfo,userLikeVo);
//                userLikeVo.setMatchRate();
                userLikeVo.setAlreadyLove(true);
                userLikeVo.setId(userLike.getLikeUserId());
                userLikeVoList.add(userLikeVo);
            }
        }
        pageResult.setItems(userLikeVoList);
        return ResponseEntity.ok(pageResult);
    }
    //展示喜欢列表
    public ResponseEntity lovePage(Integer page, Integer pagesize, String nickname) {

        Long userId = UserHolder.getUserId();
        PageResult pageResult = userLikeApi.lovePage(userId,page,pagesize);
        List<UserLike> userLikeList = (List<UserLike>) pageResult.getItems();
        List<UserLikeVo> userLikeVoList = new ArrayList<>();
        for (UserLike userLike : userLikeList){
            Boolean hasKey = redisTemplate.hasKey("already_love_"+ userLike.getLikeUserId()+"_"+userId);
            UserInfo userInfo = userInfoApi.findById(userLike.getLikeUserId());
            UserLikeVo userLikeVo = new UserLikeVo();
            //如果不喜欢我，就是喜欢
            if (!userLikeApi.isExist(userLike.getLikeUserId(),userId)){
                BeanUtils.copyProperties(userInfo,userLikeVo);
                userLikeVo.setAlreadyLove(true);
                userLikeVo.setId(userLike.getLikeUserId());
                userLikeVoList.add(userLikeVo);
            }
        }
        pageResult.setItems(userLikeVoList);
        return ResponseEntity.ok(pageResult);
    }

    //展示粉丝列表
    public ResponseEntity fansPage(Integer page, Integer pagesize, String nickname) {
        //获取当前用户di
        Long userId = UserHolder.getUserId();
        //查询：所有喜欢我的人
        PageResult pageResult = userLikeApi.getBeingLovedPage(userId,page,pagesize);
        //注：得到的集合中，userId="likeUserId",喜欢我的人的id是userlike.getUserId
        List<UserLike> userLikeList = (List<UserLike>) pageResult.getItems();
        List<UserLikeVo> userLikeVoList = new ArrayList<>();

        for (UserLike userLike : userLikeList){
            UserInfo userInfo = userInfoApi.findById(userLike.getUserId());
            UserLikeVo userLikeVo = new UserLikeVo();
            if (redisTemplate.hasKey("already_love_"+userLike.getUserId()+"_"+userId)){
                userLikeVo.setAlreadyLove(true);
            }else{
                userLikeVo.setAlreadyLove(false);
            }
//            //如果我也喜欢，就是相互喜欢
//            if (userLikeApi.isExist(userId,userLike.getUserId())){
//                userLikeVo.setAlreadyLove(false);
//            }else{
//                userLikeVo.setAlreadyLove(true);
//            }
            BeanUtils.copyProperties(userInfo,userLikeVo);
            userLikeVo.setId(userLike.getUserId());
            userLikeVoList.add(userLikeVo);
        }
        pageResult.setItems(userLikeVoList);
        return ResponseEntity.ok(pageResult);
    }

    //粉丝-喜欢
    public ResponseEntity fansLove(Long fanId) {
        Long userId = UserHolder.getUserId();
        userLikeApi.save(userId,fanId);
        //添加标记
        redisTemplate.boundValueOps("already_love_"+fanId+"_"+userId).set("");
        //记录到好友表并注册到环信上
//        friendApi.save(UserHolder.getUserId(),loveUserId);
//        huanXinTemplate.contactUsers(UserHolder.getUserId(),loveUserId);
        return ResponseEntity.ok(null);
    }

    //取消喜欢
    public ResponseEntity deleteLove(Long uid) {
        Long userId = UserHolder.getUserId();
        //删除user_like中的数据
        userLikeApi.deleteLove(userId,uid);
        //删除标记
        redisTemplate.delete("already_love_"+uid+"_"+userId);
        //删除friend中的数据
//        friendApi.deleteFriend(userId,uid);
        //删除环信的数据
//        huanXinTemplate.deleteContacts(userId,uid);
        return ResponseEntity.ok(null);
    }
}